const chalk = require('chalk');
const shell = require('shelljs');
const util = require('util');
exports.exec = util.promisify(shell.exec);
exports.execSync = util.promisify(require('child_process').execSync);
exports.execa = require('execa')
// exports.exec = require('child_process').promises.exec;

exports.shell = shell
// execute a single shell command where "cmd" is a string
exports.exec2 = function (cmd, cb) {
  // this would be way easier on a shell/bash script :P
  var child_process = require('child_process');
  var parts = cmd.split(/\s+/g);
  var p = child_process.spawn(parts[0], parts.slice(1), { stdio: 'inherit' });
  p.on('exit', function (code) {
    var err = null;
    if (code) {
      err = new Error('command "' + cmd + '" exited with wrong status code "' + code + '"');
      err.code = code;
      err.cmd = cmd;
    }
    if (cb) cb(err);
  });
};


// execute multiple commands in this.
// this could be replaced by any flow control lib
function series(cmds, cb = () => void 0) {
  var execNext = function (stdout) {
    if (cmds.length <= 0) return
    let cmd = cmds.shift()
    let options = {}
    if (Array.isArray(cmd)) {
      const [one, ...rest] = cmd
      cmd = one
      cmds.unshift(...rest)
    }

    const isObject = Object.prototype.toString.call(cmd) === '[object Object]'
    if (isObject) {
      let { cmd: val, ...rest } = cmd
      cmd = val
      options = rest
    }
    if (typeof cmd === 'function') {
      // console.log(chalk.blue('run fun: ') + chalk.magenta(cmd));
      stdout && console.log(chalk.green('stdout: ') + chalk.yellow(stdout));

      return cmd(stdout, execNext)
    }
    console.log(chalk.blue('run command: ') + chalk.magenta(cmd));
    // stdout && console.log(chalk.green('stdout: ') + chalk.yellow(stdout));

    shell.exec(cmd, options, function (err, stdout) {
      if (err) {
        cb(err);
      } else {
        if (cmds.length) execNext(stdout);
        else cb(null);
      }
    });
  };
  execNext();
};

exports.seriesa = function seriesa(cmds) {
  return new Promise((resolve, reject) => {
    function cb(err) {
      err ? reject() : resolve()
    }
    series(cmds, cb)
  })
}

exports.series = series